package test;

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * Created by antony on 2020-04-03 19:56
 */
public class ThreadPrint01 {


    private static Lock lock = new ReentrantLock();
    private static Condition con = lock.newCondition();
    static int threadNum = 3;
    private static CyclicBarrier cb = new CyclicBarrier(threadNum);

    private static volatile int idx = 0;
    private static String TEST_STR = "This is example String";
    private static int STR_LEN = TEST_STR.length();

    public static void main(String[] args) throws InterruptedException {
        PrintThread p1 = new PrintThread("A",threadNum,0);
        PrintThread p2 = new PrintThread("B",threadNum,1);
        PrintThread p3 = new PrintThread("C",threadNum,2);
        p2.start();
        p3.start();
        p1.start();



    }

    public static class PrintThread extends Thread{

        private int mod;
        private int flag;

        public PrintThread(String name, int mod, int flag) {
            super(name);
            this.mod = mod;
            this.flag = flag;
        }

        @Override
        public void run() {
            try {
                System.out.println(getName() + "-waiting...");
                cb.await();
                System.out.println(getName() + "-start...");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (BrokenBarrierException e) {
                e.printStackTrace();
            }

            while(idx < STR_LEN){
                lock.lock();
                try {
                    while(idx%mod != flag){
                        con.await();
                    }
                    if(idx >= STR_LEN){
                        return;
                    }
                    System.out.println(getName() + ":"+TEST_STR.charAt(idx));
                    idx++;
                    con.signalAll();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    lock.unlock();
                }
            }
        }
    }


    public static class StringPrint{
        public void printChar(String threadName, int flag) throws InterruptedException {
            lock.lock();
            try {
                if(idx%2 != flag){
                    con.await();
                }
                if(idx >= STR_LEN){
                    return;
                }
                System.out.println(threadName + ":" + TEST_STR.charAt(idx));
                idx++;
                con.signalAll();
            } finally {
                lock.unlock();
            }
        }
    }
}
